<template>
  <el-dialog
    :model-value="showMapDialogVisible"
    title="选择地点"
    width="1000"
    @close="handleCancel"
    :close-on-click-modal="false"
  >
    <div class="map-picker-container">
      <div class="search-bar">
        <el-input v-model="searchKeyword" placeholder="搜索地点" @keyup.enter="performSearch" />
        <el-button type="primary" @click="performSearch">搜索</el-button>
      </div>

      <div class="map-wrapper">
        <div id="map-container"></div>
        <div class="center-marker"></div>
      </div>

      <div class="info-panel" v-if="searchAddressData.length">
        <div
          v-for="(item, index) in searchAddressData"
          :key="index"
          class="search-result-item"
          :class="{ 'address-active': selectAddressId === item.id }"
          @click="selectAddress(item)"
        >
          <div>{{ item.title }} - {{ item.address }}</div>
          <div v-if="selectAddressId === item.id"
            ><el-icon size="24"><CircleCheck /></el-icon
          ></div>
        </div>
      </div>
    </div>

    <template #footer>
      <div class="buttons">
        <el-button @click="handleCancel">取消</el-button>
        <el-button type="primary" @click="handleConfirm">确认</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
  import { ref, onMounted } from 'vue'
  import { CircleCheck } from '@element-plus/icons-vue'
  import debounce from 'lodash/debounce'
  import { jsonp } from 'vue-jsonp'

  const props = defineProps({
    showMapDialogVisible: Boolean
  })

  const emit = defineEmits(['location-selected', 'cancel'])

  const searchKeyword = ref('')
  const searchAddressData = ref<any[]>([])
  const selectedLocation = ref({ lat: 30.5928, lng: 114.3055 })
  const selectAddressId = ref()

  const map = ref<any>(null)

  const loadTencentMapScript = (): Promise<void> => {
    return new Promise((resolve, reject) => {
      if ((window as any).TMap) return resolve()

      const script = document.createElement('script')
      script.src = `https://map.qq.com/api/gljs?v=1.exp&key=PDPBZ-2PV6J-2FHFT-XMW53-O5JUE-I7B6O`
      script.async = true
      script.onload = () => resolve()
      script.onerror = () => reject(new Error('腾讯地图 SDK 加载失败'))
      document.head.appendChild(script)
    })
  }

  const debouncedFetch = debounce((lat, lng) => {
    fetchNearbyAddresses(lat, lng)
  }, 600)

  function initMap() {
    const TMap = (window as any).TMap
    const center = new TMap.LatLng(selectedLocation.value.lat, selectedLocation.value.lng)

    map.value = new TMap.Map(document.getElementById('map-container'), {
      center,
      zoom: 16,
      viewMode: '2D'
    })

    map.value.on('idle', () => {
      const centerLatLng = map.value.getCenter()
      selectedLocation.value = {
        lat: centerLatLng.lat,
        lng: centerLatLng.lng
      }

      debouncedFetch(centerLatLng.lat, centerLatLng.lng)
    })
  }

  function fetchNearbyAddresses(lat: number, lng: number) {
    jsonp('https://apis.map.qq.com/ws/geocoder/v1/', {
      location: `${lat},${lng}`,
      key: 'PDPBZ-2PV6J-2FHFT-XMW53-O5JUE-I7B6O',
      get_poi: 1,
      output: 'jsonp'
    }).then((res: any) => {
      if (res.status === 0 && res.result.pois) {
        searchAddressData.value = res.result.pois
      } else {
        searchAddressData.value = []
      }
    })
  }

  function selectAddress(item: any) {
    const TMap = (window as any).TMap
    const pos = new TMap.LatLng(item.location.lat, item.location.lng)
    map.value.setCenter(pos)

    searchKeyword.value = item.address
    selectAddressId.value = item.id
    selectedLocation.value = item.location
  }

  function performSearch() {
    if (!searchKeyword.value.trim()) return
    jsonp('https://apis.map.qq.com/ws/place/v1/suggestion', {
      key: 'PDPBZ-2PV6J-2FHFT-XMW53-O5JUE-I7B6O',
      region: '全国',
      output: 'jsonp',
      keyword: searchKeyword.value.trim()
    }).then((res: any) => {
      if (res.status === 0) {
        searchAddressData.value = res.data
      }
    })
  }

  function handleConfirm() {
    emit('location-selected', selectedLocation.value)
  }

  function handleCancel() {
    emit('cancel')
  }

  onMounted(async () => {
    await loadTencentMapScript()
    initMap()
  })
</script>

<style scoped lang="scss">
  .map-picker-container {
    display: flex;
    flex-direction: column;
    width: 100%;
  }

  .search-bar {
    display: flex;
    padding: 10px;
    gap: 10px;
  }

  .map-wrapper {
    position: relative;
    width: 100%;
    height: 400px;
    margin-top: 10px;
  }

  #map-container {
    width: 100%;
    height: 100%;
  }

  .center-marker {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 32px;
    height: 32px;
    margin-left: -16px;
    margin-top: -32px;
    background: url('https://mapapi.qq.com/web/lbs/javascriptGL/demo/img/markerDefault.png')
      no-repeat center center;
    background-size: contain;
    pointer-events: none;
    z-index: 10;
  }

  .info-panel {
    padding: 10px;
    background-color: #f5f5f5;
    max-height: 200px;
    overflow-y: auto;
    margin-top: 10px;
  }

  .search-result-item {
    padding: 6px 0;
    cursor: pointer;
    font-size: 14px;
    border-bottom: 1px solid #eee;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }

  .address-active {
    color: var(--el-color-primary);
  }

  .search-result-item:hover {
    color: var(--el-color-primary);
  }

  .buttons {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
  }
</style>
